package net.oschina.aibinxiao.security.md;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD2Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;

/**
 * @Author: AiBinXiao
 * @Description: MD消息摘要算法家族
 *               不同实现方式实现相同的算法，结果一样
 *               JDK实现偏底层，但是缺少进制转换的方法
 *               BC提供了MD4的实现
 *               CC简化了MD2、MD5的实现
 * @Date: 2017/10/13 10:00
 */

public class MyMD {

    private static String src = "imooc security md";

    public static void main(String[] args) {
        jdkMD5();
        jdkMD2();
        bcMD4();
        bcMD5();
        bcMD2();
        ccMD5();
        ccMD2();
    }

    // MD5消息摘要算法 JDK实现
    public static void jdkMD5() {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] md5Bytes = md.digest(src.getBytes());
            System.out.println("JDK MD5 : " + Hex.encodeHexString(md5Bytes));
            // JDK MD5 : 89048f19b72e7367b7faacfe659a8de0
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    // MD2消息摘要算法
    public static void jdkMD2() {
        try {
            MessageDigest md = MessageDigest.getInstance("MD2");
            byte[] md2Bytes = md.digest(src.getBytes());
            System.out.println("JDK MD2 : " + Hex.encodeHexString(md2Bytes));
            // JDK MD2 : 54ade03d9765c9f0290189a2ae704ee7
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    // MD4消息摘要算法 Bouncy Castle实现
    public static void bcMD4() {
        try {
            Security.addProvider(new BouncyCastleProvider());
            MessageDigest md = MessageDigest.getInstance("MD4");
            byte[] md4Bytes = md.digest(src.getBytes());
            System.out.println("Bouncy Castle MD4 : " + Hex.encodeHexString(md4Bytes));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        // 另一种实现方式
        /*Digest digest = new MD4Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length); // 三个参数 要处理字符串的byte数组，开始索引，处理长度
        byte[] md4Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(md4Bytes, 0);
        System.out.println("Bouncy Castle MD4 : " + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));*/
        // Bouncy Castle MD4 : d4878ee1ed8379537813b3888320ad04
    }

    // MD5消息摘要算法 Bouncy Castle实现
    public static void bcMD5() {
        Digest digest = new MD5Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length); // 三个参数 要处理字符串的byte数组，开始索引，处理长度
        byte[] md5Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(md5Bytes, 0);
        System.out.println("Bouncy Castle MD5 : " + org.bouncycastle.util.encoders.Hex.toHexString(md5Bytes));
        // Bouncy Castle MD5 : 89048f19b72e7367b7faacfe659a8de0
    }

    // MD2消息摘要算法 Bouncy Castle实现
    public static void bcMD2() {
        Digest digest = new MD2Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length); // 三个参数 要处理字符串的byte数组，开始索引，处理长度
        byte[] md2Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(md2Bytes, 0);
        System.out.println("Bouncy Castle MD2 : " + org.bouncycastle.util.encoders.Hex.toHexString(md2Bytes));
        // Bouncy Castle MD2 : 54ade03d9765c9f0290189a2ae704ee7
    }

    // MD5消息摘要算法 Commons Codec实现
    public static void ccMD5() {
        System.out.println("Commons Codec MD5 : " + DigestUtils.md5Hex(src.getBytes()));
        // Commons Codec MD5 : 89048f19b72e7367b7faacfe659a8de0
    }

    // MD2消息摘要算法 Commons Codec实现
    public static void ccMD2() {
        System.out.println("Commons Codec MD2 : " + DigestUtils.md2Hex(src.getBytes()));
        // Commons Codec MD2 : 54ade03d9765c9f0290189a2ae704ee7
    }
}
